use serde::{Deserialize, Serialize};
use thiserror::Error;
use std::io;
use std::path::PathBuf;
use crate::convert::Responser;
use crate::http::{HttpReceiveError, HttpSendError};
use crate::websockt::{WebSocketReceiveError, WebSocketSendError};

#[derive(Error, Debug)]
pub enum ServerError {
    #[error("Failed to receive a http request: {0}")]
    HttpReceive(#[from] HttpReceiveError),

    #[error("Failed to send a http response: {0}")]
    HttpSend(#[from] HttpSendError),

    #[error("Failed to receive a websocket frame: {0}")]
    WebSocketReceive(#[from] WebSocketReceiveError),

    #[error("Failed to send a websocket frame: {0}")]
    WebSocketSend(#[from] WebSocketSendError),

    #[error("IO error: {0}")]
    Io(#[from] io::Error),

    #[error("Upgrade Web Socket failed: {0}")]
    UpgradeWebSocket(String),    
}

#[derive(Responser, Serialize, Deserialize)]
pub enum ServerRouteError {
    #[response(status = 400, content_type = "json")]
    InvalidBody(String),

    #[response(status = 400, content_type = "json")]
    InvalidURIArgument(String),

    #[response(status = 500, content_type = "json")]
    FailedHnalde(String),
}   

#[derive(Responser, Serialize, Deserialize)]
#[response(status = 500, content_type = "json")]
pub struct ServerResourceError {
    file_path: PathBuf,
    reason: String,
}

impl ServerResourceError {
    pub fn new<P: Into<PathBuf>, S: Into<String>>(file_path: P, reason: S) -> Self {
        Self { file_path: file_path.into(), reason: reason.into() } 
    }
}
